use strict;

use Getopt::Long;

# defaults
my $retry_num = 5;
my $from = 1;
my $to   = 16;
my $step      = 1;
my @arr_sizes  = ( 10000, 100000, 1000000);

&main();


sub main()
{
    &init_vars();

    foreach my $arr_size ( @arr_sizes)
    {
        my @results;
        for ( my $proc_num = $from; $proc_num < $to; $proc_num += $step )
        {
            push @results, &iter( $proc_num, $arr_size);
        }
        print scalar @results;

        open( my $fh, ">", "stats/2a.$arr_size") or die "cannot open: $!";
        print $fh "proc_num time\n";
        foreach my $res ( @results)
        {
            $| = 1;
            print $fh ( 
                         $res->{proc_num} ." " 
                        .$res->{bcast}    ." "
                        .$res->{calc}     ." "
                        .$res->{red}      ." "
                        .$res->{time}     ." "
                        .$res->{res}      ."\n"
                    ); 
        }
        close $fh;
    }
    return 0; 
}

sub init_vars
{
    my $result = &GetOptions (
        "from=i"        => \$from, 
        "to=i"          => \$to,
        "step=i"        => \$step,
    );
}

sub cpu_wait
{
    my $time = 3;
    while (1)
    {
        my $cpu = `cat /proc/loadavg`;
        if ( $cpu =~ /^(\d*\.\d*)/)
        {
            if ( $1 < 6.0)
            {
                return;
            } 
        }
        print "Waiting $time. Cpu load $1\n";
        sleep $time;
    }
}

sub iter()
{
    my $proc_num = shift;
    my $arr_size = shift;
    my %res;
   
    $res{time} = 0;
    $res{bcast} = 0;
    $res{calc}  = 0;
    $res{red}   = 0;
    
    $res{proc_num} = $proc_num;

    for ( my $i = 0; $i < $retry_num; $i++)
    {
        &cpu_wait();
        my $tmp = $arr_size + 3;
        my $res = `./bin/gen_array $tmp |  mpiexec -n $proc_num ./bin/2a 2>err`;
        print $proc_num . "\t" . $arr_size . "\n";
        if ( $res =~ /Result:\s(\d*)\s(\d*)\s(\d*)\s(\d*)\s(OK|FAIL)/)
        {
            $res{bcast}  = ( $res{bcast}  * $i + $1) / ( $i + 1);
            $res{calc}  = ( $res{calc}  * $i + $2) / ( $i + 1);
            $res{red}  = ( $res{red}  * $i + $3) / ( $i + 1);
            $res{time}  = ( $res{time}  * $i + $4) / ( $i + 1);
             
            $res{res}   = $5;
        }
    }

    return \%res;
}


